<?php
// +----------------------------------------------------------------------
// | zhanshop-server / Device.php    [ 2023/12/13 11:10 ]
// +----------------------------------------------------------------------
// | Copyright (c) 2011~2023 zhangqiquan All rights reserved.
// +----------------------------------------------------------------------
// | Author: zhangqiquan <768617998@qq.com>
// +----------------------------------------------------------------------
declare (strict_types=1);

namespace app\api\admin\v1\controller;

use app\api\admin\Controller;
use zhanshop\App;
use zhanshop\Log;
use zhanshop\Request;
use zhanshop\Response;
use zhanshop\ShareData;

class Bridge extends Controller
{
    protected $domain = '';
    protected $proxyPort = 0;

    public function __construct()
    {
        $this->domain = App::env()->get("BRIDGE_DOMAIN", 'mallzi.com');
        $servers = App::config()->get("server.servers");
        foreach ($servers as $server) {
            if($server['name'] == 'httpproxy'){
                $this->proxyPort = $server['port'];
            }
        }
    }
    /**
     * @api TCP establish 桥接客户端连接到服务中心
     * @apiGroup 桥接
     */
    public function establish(Request $request, Response $response)
    {
        $fd = $request->fd();
        $name = $request->post('name');
        $version = $request->post('version', '');

        if($name && $response->toSend($fd, $fd)){
            $proxy = "";
            $data = [
                'fd' => $fd,
                'ip' => $request->server('remote_addr'),
                'name' => $name,
                'version' => $version,
                'proxy' => $proxy,
                'connect_time' => $request->time()
            ];
            ShareData::set($fd, $data);
        }
    }

    /**
     * @api TCP message/{tofd}/{event} 桥客户端向服务端吐出来消息
     * @apiGroup 桥接
     */
    public function message(Request $request, Response $response)
    {
        $event = $request->getData('event');
        $tofd = intval($request->getData('tofd'));
        $connInfo = $response->rawResponse()->connection_info($tofd);
        if(($connInfo['uid'] ?? false) == false) return;
        $data64 = $request->post();
        if(is_string($data64)){
            $data = base64_decode($data64); // 解码一下
            if($event == "result"){
                $ok = $response->toSend($tofd, $data, ""); // 把结果转发出去 这里响应是原封不动的发出 如果需要加\r\n 也应该是桥接客户端加
                if($ok == false){
                    $response->toSend($request->fd(), json_encode([
                            'uri' => '/v1/proxy.close/'.$tofd,
                            'header' => [],
                            'body' => ""
                        ])."\r\n");
                    // 这里需要优化
                    $response->rawResponse()->close($tofd);
                }
            }else if($event == "close"){
                $response->rawResponse()->close($tofd);
            }else{
                Log::errorLog(5, "桥接客户端错误消息：".print_r($data, true));
            }
        }
    }

    /**
     * @api TCP push 准备向设备推送消息
     * @apiGroup 命令终端
     */
    public function getPush(Request $request, Response $response)
    {
        $response->toSend($request->fd(), $request->fd());
    }

    /**
     * @api TCP push/{tofd} 向设备推送消息
     * @apiGroup 桥接
     */
    public function postPush(Request $request, Response $response)
    {
        $tofd = intval($request->getData('tofd'));
        $data = $request->post();
        $response->toSend($tofd, $data); // 把消息转发出去
    }


    /**
     * @api TCP pool/{auth} 桥接池
     * @apiGroup 桥接
     */
    public function pool(Request $request, Response $response){

        list($proxyHost) = explode(":", $request->header('host'));
        $count = 0;
        $list = [];
        foreach (ShareData::getInstance() as $row){
            $list[] = [
                'name' => $row['name'],
                'proxy' => [
                    'host' => $proxyHost,
                    'http_port' => $this->proxyPort,
                    'user' => str_replace('%', '_', urlencode(App::aes()->encrypt($row['fd'].','.$request->time()))),
                    'pwd' => str_replace('%', '_', urlencode(App::aes()->encrypt("zhangqiquan".','.$request->time()))),
                ],
                'online' => $request->time() - $row['connect_time'],
            ];
            $count++;
            if($count > 2000) break;
        }
        $response->toSend($request->fd(), $list);
    }
    /**
     * @api GET warn 获取警告信息
     * @apiGroup 桥接
     */
    public function getWarn(Request $request, Response $response)
    {
        $warnId = $request->get('id');
        $result = [];
        if($warnId){
            $ids = explode(',', $warnId);
            $errors = App::database()->model("server_warn")->whereIn('id', $ids)->select();
            $errorStr = '';
            foreach ($errors as $val){
                $errorStr .= $val['file'].' '.$val['client_ip'].PHP_EOL.'错误码 => '.$val['code'].', 内容 => '.$val['msg'].PHP_EOL.PHP_EOL;
            }
            return $errorStr;
        }
        return $this->result($result);
    }
}